

// const userServiceError = require('./exp/userServiceError/userServiceError')

const { options } = require("../router/router")

class baseService{

    constructor(model,beanClass,expClass){
        this.model = model
        this.bean  = new  beanClass()
        this.expClass = expClass
        this.beanClass2 = beanClass
    }

    async aggregateService(grass){
        let  result
        try {
            result = await  this.model.aggregate(grass)
        } catch (error) {
            throw new this.expClass(error)
        }

        return result
    }


    async findOneService(grass){

    
        let  result
        try {
            result = await  this.model.findOne(grass,{"kemuIDArray":true}).populate("kemuIDArray")
        } catch (error) {
            throw new this.expClass(error)
        }

        if(result){
            return result
         }else{
            throw  new this.expClass()
         }


    }



  async  create(data){

    if(data instanceof Array){
        let result=[]
        for (const item of data) {
            let aa = new this.beanClass2()
            for (const key1 in item) {
                for (const key2 in aa) {
                    if(key1 == key2){
                       
                        aa[key2] = item[key1]
                    }
                }
            }
            let bb
            try {
                 bb = await new this.model(aa).save()
            } catch (error) {
                throw new this.expClass(error)
            }
            if(bb){
                result.push(bb)
            }else {
                throw  new this.expClass()
            }
        }
        return result
    }else if(Object.prototype.toString.call(data) === '[object Object]') {
        let  result 
        for (const key1 in data) {
            for (const key2 in this.bean) {
                if(key1 == key2){
                    this.bean[key2] = data[key1]
                }
            }
        }
    
        try {
            result  =  await new this.model(this.bean).save()
        } catch (error) {
            throw new this.expClass(error)
        }
         if(result){
            return result
         }else{
            throw  new this.expClass()
         }

    }
    

    }

  async   findByIdAndRemove(data){
        let  result
        try {
            result = await  this.model.findByIdAndRemove(data.id)
        } catch (error) {
            throw new this.expClass(error)
        }

        if(result){
            return result
         }else{
            throw  new this.expClass()
         }
    }

    
    async findByIdAndUpdate(id,updateContent){

        let  result
        try {
            result = await  this.model.findByIdAndUpdate(id,updateContent)
        } catch (error) {
            console.log(error);
            throw new this.expClass(error)
        }
        if(result){
            return result
         }else{
            throw  new this.expClass()
         }
    }


    async findOne(conditions,hides,fills,skip,limit){
   
        let  result
        if(fills==undefined||Object.keys(fills).length==0){
            try {
                result = await  this.model.findOne(conditions,hides).skip(skip).limit(limit)
            } catch (error) {
                throw new this.expClass(error)
            }
            if(result){
                return result
             }else{
                throw  new this.expClass()
             }
        }else {
            switch (Object.keys(fills).length) {
                case 1:
                    try {
                        result = await  this.model.findOne(conditions,hides).populate(Object.values(fills)[0]).skip(skip).limit(limit)
                    } catch (error) {
                        throw new this.expClass(error)
                    }
                    if(result){
                        return result
                     }else{
                        throw  new this.expClass()
                     }
                    break;
                case 2:
                    try {
                        result = await  this.model.findOne(conditions,hides).populate(Object.values(fills)[0]).populate(Object.values(fills)[1]).skip(skip).limit(limit)
                    } catch (error) {
                        throw new this.expClass(error)
                    }
                    if(result){
                        return result
                     }else{
                        throw  new this.expClass()
                     }
                  break;
                  case 3:
                    try {
                  
                        result = await  this.model.findOne(conditions,hides).populate(Object.values(fills)[0]).populate(Object.values(fills)[1]).populate(Object.values(fills)[2]).skip(skip).limit(limit)
                    } catch (error) {
                        throw new this.expClass(error)
                    }
                    if(result){
                        return result
                     }else{
                        throw  new this.expClass()
                     }
                  break;
                  case 4:
                    try {
                        result  = await  this.model.findOne(conditions,hides).populate(Object.values(fills)[0]).populate(Object.values(fills)[1]).populate(Object.values(fills)[2]).populate(Object.values(fills)[3]).skip(skip).limit(limit)
                    } catch (error) {
                        throw new this.expClass(error)
                    }
                    if(result){
                        return result
                     }else{
                        throw  new this.expClass()
                     }
                  break;

             
     
    
              }

        }
        
   

        }


    async find(conditions,hides,fills,skip,limit){
        let  result
        if(fills==undefined||Object.keys(fills).length==0){

            try {
                result = await  this.model.find(conditions,hides).skip(skip).limit(limit)
            } catch (error) {
                throw new this.expClass(error)
            }
            if(result){
                return result
             }else{
                throw  new this.expClass()
             }
        }else {
            switch (Object.keys(fills).length) {
                case 1:
                    try {
                        console.log(1);
                        result = await  this.model.find(conditions,hides).populate(Object.values(fills)[0]).skip(skip).limit(limit)
                    } catch (error) {
                        throw new this.expClass(error)
                    }
                    if(result){
                        return result
                     }else{
                        throw  new this.expClass()
                     }
                    break;
                case 2:
                    try {
                        console.log(2);
                        result = await  this.model.find(conditions,hides).populate(Object.values(fills)[0]).populate(Object.values(fills)[1]).skip(skip).limit(limit)
                    } catch (error) {
                        throw new this.expClass(error)
                    }
                    if(result){
                        return result
                     }else{
                        throw  new this.expClass()
                     }
                  break;
                  case 3:
                    try {
                        console.log(33);
                        result = await  this.model.find(conditions,hides).populate(Object.values(fills)[0]).populate(Object.values(fills)[1]).populate(Object.values(fills)[2]).skip(skip).limit(limit)
                    } catch (error) {
                        throw new this.expClass(error)
                    }
                    if(result){
                        return result
                     }else{
                        throw  new this.expClass()
                     }
                  break;
                  case 4:
                    try {
                        result = await  this.model.find(conditions,hides).populate(Object.values(fills)[0]).populate(Object.values(fills)[1]).populate(Object.values(fills)[2]).populate(Object.values(fills)[3]).skip(skip).limit(limit)
                    } catch (error) {
                        throw new this.expClass(error)
                    }
                    if(result){
                        return result
                     }else{
                        throw  new this.expClass()
                     }
                  break;
              }

        }
        
   

        }




    


    async queryAll(param1,param2){
        let  result


        if(arguments.length==0 ){
            try {
                result = await  this.model.find()
            } catch (error) {
                throw new this.expClass(error)
            }
            if(result){
                return result
             }else{
                throw  new this.expClass()
             }
        }else if(arguments.length==1){
            try {
                result = await  this.model.find().populate(param1)
            } catch (error) {
                throw new this.expClass(error)
            }
            if(result){
                return result
             }else{
                throw  new this.expClass()
             }
        }else if(arguments.length==2){
            try {
                result = await  this.model.find().populate(param1).populate(param2)
            } catch (error) {
                throw new this.expClass(error)
            }
            if(result){
                return result
             }else{
                throw  new this.expClass()
             }

        }




    }

    async findByIdAndPopulate(id,param1,param2){
      
        let  result
        if(arguments.length==1){
            try {
                result = await  this.model.findById(id)
            } catch (error) {
                throw new this.expClass(error)
            }
            if(result){
                return result
             }else{
                throw  new this.expClass()
             }
        }else if(arguments.length==2){
            try {
                result = await  this.model.findById(id).populate(param1)
            } catch (error) {
               
                throw new this.expClass(error)
            }
            if(result){
                return result
             }else{
                throw  new this.expClass()
             }
        }else if(arguments.length==3){
       
            try {
                result = await  this.model.findById(id).populate(param1).populate(param2)
            } catch (error) {
               
                throw new this.expClass(error)
            }
            console.log(result,77);
            if(result){
                return result
             }else{
                throw  new this.expClass()
             }

        }

    }


    async findByObj(obj,param1,param2){
        if(arguments.length==1){
            let  result
            try {
                result = await  this.model.find(obj)
            } catch (error) {
                throw new this.expClass(error)
            }
    
            if(result){
                return result
             }else{
                throw  new this.expClass()
             }
        }else if(arguments.length==2){
     
            let  result
            try {
                result = await  this.model.find(obj).populate(param1)
            } catch (error) {
                throw new this.expClass(error)
            }
    
            if(result){
                return result
             }else{
                throw  new this.expClass()
             }
        }else if(arguments.length==3){
            let  result
            try {
                result = await  this.model.find(obj).populate(param1).populate(param2)
            } catch (error) {
                throw new this.expClass(error)
            }
            if(result){
                return result
             }else{
                throw  new this.expClass()
             }
        }
    }



    async findAndPopulate(obj,param1,param2){
        let result
        if(arguments.length==1){
            try {
                result = await  this.model.find(obj)
            } catch (error) {
                throw new this.expClass(error)
            }
            if(result){
                return result
             }else{
                throw  new this.expClass()
             }
        }else if(arguments.length==2){
   
            try {
                result = await  this.model.find(obj).populate(param1)
            } catch (error) {
                throw new this.expClass(error)
            }
            if(result){
                return result
             }else{
                throw  new this.expClass()
             }

        }else if(arguments.length==3){
            try {
                result = await  this.model.find(obj).populate(param1).populate(param2)
            } catch (error) {
                throw new this.expClass(error)
            }
            if(result){
                return result
             }else{
                throw  new this.expClass()
             }
        }
    }

    async findByObjAndUpdate(obj,content,options){
        let result
        try {
            result = await  this.model.findOneAndUpdate(obj,content,options)
        } catch (error) {
            throw new this.expClass(error)
        }
        if(result){
            return result
         }else{
            throw  new this.expClass()
         }
    }


    // 更新数组
    async findByObjAndUpdateArray(obj,content){
        let result
        try {
            result = await  this.model.findOneAndUpdate(obj,{$addToSet:content})
        } catch (error) {
            throw new this.expClass(error)
        }
        if(result){
            return result
         }else{
            throw  new this.expClass()
         }
    }


    // 存在则更新,不存在则新增
    async findOneAndUpdate(conditions,updates,options){

  
        let  result

        try {
            result = await  this.model.findOneAndUpdate(conditions,updates,options)
        } catch (error) {
            console.log(error,111);
            throw new this.expClass(error)
        }

        return result
    }






    
}

module.exports={baseService}